#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
昆明地铁数据分析与可视化 - 第三部分
本部分实现昆明地铁客流量分析功能
分析基于已投入运营的地铁站点数据
"""

import os
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib.font_manager import FontProperties
import matplotlib.dates as mdates
from matplotlib.ticker import FuncFormatter
import matplotlib.patches as mpatches
import warnings
import datetime
import calendar
from pathlib import Path
from kunming_metro_analysis_part1 import load_data, extract_city_data

# 忽略警告
warnings.filterwarnings('ignore')

# 设置中文字体
try:
    font = FontProperties(fname=r"C:\Windows\Fonts\SimHei.ttf")
    plt.rcParams['font.sans-serif'] = ['SimHei']
    plt.rcParams['axes.unicode_minus'] = False
except:
    print("无法加载SimHei字体，使用系统默认字体")

# 创建输出目录
output_dir = "analysis_results/kunming_analysis"
os.makedirs(output_dir, exist_ok=True)

def analyze_flow(kunming_flow):
    """分析昆明地铁客流量数据"""
    if kunming_flow is None or kunming_flow.empty:
        print("没有可分析的昆明客流量数据")
        return None
    
    print("\n=== 昆明地铁客流量分析 ===")
    
    # 基本统计信息
    mean_flow = kunming_flow['客流量'].mean()
    max_flow = kunming_flow['客流量'].max()
    min_flow = kunming_flow['客流量'].min()
    median_flow = kunming_flow['客流量'].median()
    
    print(f"平均日客流量: {mean_flow:.2f}万人次")
    print(f"最高日客流量: {max_flow:.2f}万人次")
    print(f"最低日客流量: {min_flow:.2f}万人次")
    print(f"中位数日客流量: {median_flow:.2f}万人次")
    
    # 时间序列分析 - 客流量趋势
    plt.figure(figsize=(14, 7))
    plt.plot(kunming_flow['日期'], kunming_flow['客流量'], marker='', linestyle='-', linewidth=2)
    
    # 添加趋势线
    z = np.polyfit(range(len(kunming_flow)), kunming_flow['客流量'], 1)
    p = np.poly1d(z)
    plt.plot(kunming_flow['日期'], p(range(len(kunming_flow))), "r--", linewidth=1)
    
    plt.title('昆明地铁日客流量变化趋势')
    plt.xlabel('日期')
    plt.ylabel('客流量（万人次）')
    plt.grid(True, linestyle='--', alpha=0.7)
    plt.xticks(rotation=45)
    plt.tight_layout()
    plt.savefig(f"{output_dir}/kunming_daily_flow_trend.png", dpi=300)
    plt.close()
    print("日客流量变化趋势图已保存")
    
    # 工作日vs周末客流量对比
    analyze_weekday_weekend_flow(kunming_flow)
    
    # 月度客流量分析
    analyze_monthly_flow(kunming_flow)
    
    # 客流量与其他城市对比
    compare_flow_with_other_cities(kunming_flow)
    
    return {'mean_flow': mean_flow, 'max_flow': max_flow, 'min_flow': min_flow, 'median_flow': median_flow}

def analyze_weekday_weekend_flow(kunming_flow):
    """分析工作日与周末客流量对比"""
    weekday_flow = kunming_flow[kunming_flow['是否周末'] == 0]['客流量'].mean()
    weekend_flow = kunming_flow[kunming_flow['是否周末'] == 1]['客流量'].mean()
    
    print(f"工作日平均客流量: {weekday_flow:.2f}万人次")
    print(f"周末平均客流量: {weekend_flow:.2f}万人次")
    print(f"周末/工作日客流量比: {weekend_flow / weekday_flow:.2f}")
    
    # 绘制工作日vs周末客流量对比图
    plt.figure(figsize=(8, 6))
    bars = plt.bar(['工作日', '周末'], [weekday_flow, weekend_flow], color=['blue', 'orange'])
    plt.title('昆明地铁工作日与周末客流量对比')
    plt.ylabel('平均客流量（万人次）')
    
    # 在柱状图上添加数值标签
    for bar in bars:
        height = bar.get_height()
        plt.text(bar.get_x() + bar.get_width()/2., height + 0.5,
                f'{height:.2f}', ha='center', va='bottom')
    
    plt.grid(True, axis='y', linestyle='--', alpha=0.7)
    plt.tight_layout()
    plt.savefig(f"{output_dir}/kunming_weekday_weekend_comparison.png", dpi=300)
    plt.close()
    print("工作日与周末客流量对比图已保存")
    
    # 按星期几分析客流量
    weekday_means = kunming_flow.groupby('星期')['客流量'].mean()
    
    # 转换星期索引为星期名称
    weekday_names = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
    weekday_means.index = [weekday_names[i] for i in weekday_means.index]
    
    # 绘制按星期几的平均客流量
    plt.figure(figsize=(10, 6))
    bars = plt.bar(weekday_means.index, weekday_means.values, color=sns.color_palette("Blues_d", 7))
    plt.title('昆明地铁各星期平均客流量')
    plt.ylabel('平均客流量（万人次）')
    plt.grid(True, axis='y', linestyle='--', alpha=0.7)
    
    # 在柱状图上添加数值标签
    for bar in bars:
        height = bar.get_height()
        plt.text(bar.get_x() + bar.get_width()/2., height + 0.5,
                f'{height:.2f}', ha='center', va='bottom')
    
    plt.tight_layout()
    plt.savefig(f"{output_dir}/kunming_weekday_flow.png", dpi=300)
    plt.close()
    print("各星期客流量对比图已保存")

def analyze_monthly_flow(kunming_flow):
    """分析月度客流量趋势"""
    # 按月份分析客流量
    monthly_flow = kunming_flow.groupby('月份')['客流量'].mean()
    
    # 绘制月度平均客流量
    plt.figure(figsize=(12, 6))
    ax = plt.bar(monthly_flow.index, monthly_flow.values, color=sns.color_palette("Blues_d", len(monthly_flow)))
    plt.title('昆明地铁月度平均客流量')
    plt.xlabel('月份')
    plt.ylabel('平均客流量（万人次）')
    plt.xticks(range(1, 13))
    plt.grid(True, linestyle='--', alpha=0.7)
    
    # 在柱状图上添加数值标签
    for i, v in enumerate(monthly_flow.values):
        plt.text(monthly_flow.index[i], v + 0.5, f'{v:.2f}', ha='center')
    
    plt.tight_layout()
    plt.savefig(f"{output_dir}/kunming_monthly_flow.png", dpi=300)
    plt.close()
    print("月度平均客流量图已保存")
    
    # 创建客流量热力图
    if len(kunming_flow) >= 30:  # 确保有足够的数据
        # 创建按日期和星期的透视表
        flow_pivot = create_flow_heatmap(kunming_flow)
        
        # 绘制客流量热力图
        plt.figure(figsize=(14, 8))
        sns.heatmap(flow_pivot, cmap="YlGnBu", linewidths=0.5, annot=False)
        plt.title('昆明地铁客流量热力图 (按星期和月份)')
        plt.ylabel('星期')
        plt.xlabel('月份')
        plt.tight_layout()
        plt.savefig(f"{output_dir}/kunming_flow_heatmap.png", dpi=300)
        plt.close()
        print("客流量热力图已保存")

def create_flow_heatmap(kunming_flow):
    """创建按星期和月份的客流量热力图数据"""
    # 将星期名称添加到数据中
    weekday_names = ['周一', '周二', '周三', '周四', '周五', '周六', '周日']
    kunming_flow['星期名'] = kunming_flow['星期'].apply(lambda x: weekday_names[x])
    
    # 创建透视表
    flow_pivot = pd.pivot_table(
        kunming_flow, 
        values='客流量', 
        index='星期名',
        columns='月份', 
        aggfunc='mean'
    )
    
    # 确保星期按周一到周日排序
    flow_pivot = flow_pivot.reindex(weekday_names)
    
    return flow_pivot

def compare_flow_with_other_cities(kunming_flow):
    """将昆明地铁客流量与其他城市进行对比"""
    print("\n=== 昆明地铁与其他城市客流量对比分析 ===")
    
    # 加载所有城市的客流量数据
    data_dir = Path("data/processed/cleaned_data")
    flow_path = data_dir / "cleaned_flow_data.csv"
    flow_df = pd.read_csv(flow_path)
    
    # 检查客流量数据格式
    print(f"客流量数据维度: {flow_df.shape}")
    print(f"客流量数据列名: {list(flow_df.columns)[:10]}...")
    
    # 获取所有可能包含城市数据的列
    city_columns = []
    excluded_columns = ['日期', '指标名称', '单位', '来源', 'index']
    
    for col in flow_df.columns:
        if col not in excluded_columns and not col.startswith('Unnamed'):
            city_columns.append(col)
    
    city_names = []
    for col in city_columns:
        if ':' in col:
            city_names.append(col.split(':')[0])
        else:
            city_names.append(col)
    
    city_names = list(set(city_names))  # 去重
    print(f"找到{len(city_names)}个城市的客流量数据: {', '.join(city_names[:10])}...")
    
    # 创建比较的DataFrame
    comparison_data = {}
    
    date_col = None
    for col in flow_df.columns:
        if '日期' in col or 'date' in col.lower() or '时间' in col:
            date_col = col
            break
    
    # 判断数据格式，确定是否需要跳过前几行
    skip_rows = 0
    if '指标名称' in flow_df.columns:
        # 可能需要跳过前几行
        if len(flow_df) > 3:
            skip_rows = 3
    
    for city_name in city_names:
        try:
            # 找出对应的列
            city_col = None
            if f"{city_name}:地铁客流量" in flow_df.columns:
                city_col = f"{city_name}:地铁客流量"
            elif f"{city_name}：地铁客流量" in flow_df.columns:
                city_col = f"{city_name}：地铁客流量"
            elif city_name in flow_df.columns:
                city_col = city_name
            
            if not city_col:
                continue
                
            # 转换为数值，将非数值转换为NaN
            if skip_rows > 0:
                city_values = pd.to_numeric(flow_df[city_col].iloc[skip_rows:], errors='coerce')
            else:
                city_values = pd.to_numeric(flow_df[city_col], errors='coerce')
                
            # 跳过NaN值
            avg_flow = city_values.dropna().mean()
            if not pd.isna(avg_flow):
                comparison_data[city_name] = avg_flow
                print(f"{city_name}平均日客流量: {avg_flow:.2f}万人次")
        except Exception as e:
            print(f"处理{city_name}客流量数据时出错: {str(e)}")
    
    # 转换为DataFrame并排序
    comparison_df = pd.DataFrame({'城市': list(comparison_data.keys()), 
                                '平均日客流量(万人次)': list(comparison_data.values())})
    comparison_df = comparison_df.sort_values('平均日客流量(万人次)', ascending=False)
    
    # 找出昆明的排名
    if '昆明' in comparison_df['城市'].values:
        kunming_rank = comparison_df['城市'].tolist().index('昆明') + 1
        kunming_flow_value = comparison_df[comparison_df['城市'] == '昆明']['平均日客流量(万人次)'].values[0]
        print(f"昆明地铁客流量在全国{len(comparison_df)}个城市中排名第{kunming_rank}位")
    else:
        print("未找到昆明的客流量排名数据")
    
    # 创建全国所有城市客流量对比图
    plt.figure(figsize=(14, 10))
    
    # 为昆明设置不同的颜色
    colors = ['skyblue'] * len(comparison_df)
    kunming_idx = comparison_df[comparison_df['城市'] == '昆明'].index
    if not kunming_idx.empty:
        colors[comparison_df.index.get_loc(kunming_idx[0])] = 'red'
    
    # 绘制水平条形图，以便显示更多城市
    bars = plt.barh(comparison_df['城市'], comparison_df['平均日客流量(万人次)'], color=colors)
    plt.title('全国地铁城市日均客流量排名')
    plt.ylabel('城市')
    plt.xlabel('平均日客流量(万人次)')
    plt.grid(axis='x', linestyle='--', alpha=0.7)
    
    # 添加数值标签
    for bar in bars:
        width = bar.get_width()
        plt.text(width + 3, bar.get_y() + bar.get_height()/2, f'{width:.1f}', 
                ha='left', va='center')
    
    # 增加图表右侧的空间，以便数值标签不会被截断
    plt.subplots_adjust(right=0.85)
    
    plt.tight_layout()
    plt.savefig(f"{output_dir}/national_flow_ranking.png", dpi=300)
    plt.close()
    
    print("全国地铁城市客流量排名图已保存")
    
    # 绘制城市客流量对比条形图 (主要城市)
    plt.figure(figsize=(12, 8))
    
    # 获取排名前15的城市进行对比
    top_cities = comparison_df.head(15).copy()
    
    # 如果昆明不在前15名，将其添加进去
    if '昆明' not in top_cities['城市'].values and '昆明' in comparison_df['城市'].values:
        kunming_data = comparison_df[comparison_df['城市'] == '昆明']
        top_cities = pd.concat([top_cities, kunming_data])
    
    # 为昆明设置不同的颜色
    colors = ['skyblue'] * len(top_cities)
    kunming_idx = top_cities[top_cities['城市'] == '昆明'].index
    if not kunming_idx.empty:
        colors[top_cities.index.get_loc(kunming_idx[0])] = 'red'
    
    # 绘制条形图
    plt.bar(top_cities['城市'], top_cities['平均日客流量(万人次)'], color=colors)
    plt.title('昆明与主要城市地铁日均客流量对比')
    plt.xlabel('城市')
    plt.ylabel('平均日客流量(万人次)')
    plt.xticks(rotation=45)
    plt.grid(axis='y', linestyle='--', alpha=0.7)
    
    # 添加数值标签
    for i, v in enumerate(top_cities['平均日客流量(万人次)']):
        plt.text(i, v + 5, f'{v:.1f}', ha='center')
    
    plt.tight_layout()
    plt.savefig(f"{output_dir}/kunming_city_flow_comparison.png", dpi=300)
    plt.close()
    
    print("城市客流量对比图已保存")
    
    # 分析与相近城市的对比
    # 根据客流量大小找出与昆明最接近的5个城市
    try:
        if '昆明' in comparison_df['城市'].values:
            kunming_flow_value = comparison_df[comparison_df['城市'] == '昆明']['平均日客流量(万人次)'].values[0]
            comparison_df['差值'] = abs(comparison_df['平均日客流量(万人次)'] - kunming_flow_value)
            similar_cities = comparison_df[comparison_df['城市'] != '昆明'].sort_values('差值').head(5)
            
            print("\n与昆明客流量最接近的城市:")
            for _, row in similar_cities.iterrows():
                print(f"{row['城市']}: {row['平均日客流量(万人次)']:.2f}万人次, 差值: {row['差值']:.2f}万人次")
            
            # 绘制昆明与相近城市对比图
            plt.figure(figsize=(10, 6))
            
            # 准备数据
            similar_df = pd.DataFrame({'城市': ['昆明'] + similar_cities['城市'].tolist(),
                                     '平均日客流量(万人次)': [kunming_flow_value] + similar_cities['平均日客流量(万人次)'].tolist()})
            
            # 为昆明设置不同的颜色
            colors = ['red'] + ['skyblue'] * len(similar_cities)
            
            # 绘制条形图
            plt.bar(similar_df['城市'], similar_df['平均日客流量(万人次)'], color=colors)
            plt.title('昆明与相似客流量城市对比')
            plt.xlabel('城市')
            plt.ylabel('平均日客流量(万人次)')
            plt.grid(axis='y', linestyle='--', alpha=0.7)
            
            # 添加数值标签
            for i, v in enumerate(similar_df['平均日客流量(万人次)']):
                plt.text(i, v + 1, f'{v:.1f}', ha='center')
            
            plt.tight_layout()
            plt.savefig(f"{output_dir}/kunming_similar_cities_comparison.png", dpi=300)
            plt.close()
            
            print("昆明与相似城市对比图已保存")
    except Exception as e:
        print(f"生成相似城市对比图失败: {str(e)}")
    
    return

if __name__ == "__main__":
    # 加载数据
    stations_2023_df, lines_2023_df, stations_2024_df, lines_2024_df, flow_df = load_data()
    
    # 提取昆明数据
    _, _, kunming_flow = extract_city_data(stations_2023_df, lines_2023_df, flow_df, "昆明")
    
    # 分析客流量
    if kunming_flow is not None and not kunming_flow.empty:
        analyze_flow(kunming_flow)
    else:
        print("未能获取昆明客流量数据，无法进行客流量分析") 